<!DOCTYPE html>
<html>
  <head><meta name="generator" content="Hexo 3.9.0">
<meta name="google-site-verification" content="fQ_tfBgNjE9NQcpKnGAkWapHoKuimF5lVuNuqpPXar0">
    <meta charset="utf-8">
    
    <title>(转载)JavaScript原型链污染攻击学习笔记 | Xiao Leung&#39;s Blog</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    
    
      <link rel="icon" href="/favicon.png">
    

    <link rel="stylesheet" href="/css/style.css">

    <link rel="stylesheet" href="/js/google-code-prettify/tomorrow-night-eighties.min.css">

  </head>

  <body>
<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body></html>
<header>

	<a id="logo" href="/" title="Xiao Leung&#39;s Blog">
	<img src="/favicon.png" alt="Xiao Leung&#39;s Blog"></a>
	
	
		<!--搜索栏-->
		<i class="js-toggle-search iconfont icon-search"></i>


<form class="js-search search-form search-form--modal" method="get" action="http://gushi.li" role="search">
	<div class="search-form__inner">
		<div>
			<i class="iconfont icon-search"></i>
			<input class="text-input" placeholder="Enter Key..." type="search">
		</div>
	</div>
</form>
	

	
		<!--侧边导航栏-->
		<a id="nav-toggle" href="#"><span></span></a>

<nav>
	<div class="menu-top-container">
		<ul id="menu-top" class="menu">
			
				
				<li class="current-menu-item">
					<a href="https://www.plasf.cn/2019/08/01/HelloWorld/" target="_blank">AboutMe</a>
				</li>
			
				
				<li class="current-menu-item">
					<a href="https://www.plasf.cn/HXCTF/" target="_blank">HXCTF</a>
				</li>
			
		</ul>
	</div>
</nav>
	

</header>

<div class="m-header ">
	<section id="hero1" class="hero">
		<div class="inner">
		</div>
	</section>
	
		<figure class="top-image" data-enable=true></figure>
	
</div>

<!--文章列表-->
<div class="wrapper">
  
    <!--文章-->
<article>
	
  
    <h1 class="post-title" itemprop="name">
      (转载)JavaScript原型链污染攻击学习笔记
    </h1>
  

	<div class='post-body mb'>
		<h1 id="Js面向对象的特点"><a href="#Js面向对象的特点" class="headerlink" title="Js面向对象的特点"></a>Js面向对象的特点</h1><pre><code class="javascript">d={&quot;d&quot;:&quot;ddd&quot;,dd:dd()}
-&gt;Object{d:&quot;ddd&quot;,dd:dd)()}
d.dd-&gt;fuction dd()
d.d-&gt;&quot;ddd&quot;
d[&#39;d&#39;]-&gt;&quot;ddd&quot;</code></pre>
<p>也就是说在JavaScript中能够使用多种方法去操作对象。</p>
<h1 id="prototype和-proto"><a href="#prototype和-proto" class="headerlink" title="prototype和_proto_"></a>prototype和_proto_</h1><ul>
<li><p>JavaScript中要定义一个类需要使用构造函数的方式去定义:</p>
</li>
<li><p>例如：</p>
</li>
</ul>
<pre><code class="javascript">function foo(){
this.bar = 1;
}
new foo()</code></pre>
<ul>
<li>当然和其他语言的类一样能够在类内部构造方法。</li>
<li>例如:</li>
</ul>
<pre><code class="javascript">function Foo() {
    this.bar = 1
    this.show = function() {
        console.log(this.bar)
    }
}

(new Foo()).show()</code></pre>
<ul>
<li>但是每次实例化类时候都会执行一次this.show = function…，这个show是绑定在对象上而非在类中。如果希望new类时候希望只创建一次show方法，那么就需要使用prototype(原型)：</li>
</ul>
<pre><code class="javascript">function Foo() {
    this.bar = 1
}

Foo.prototype.show = function show() {
    console.log(this.bar)
}

let foo = new Foo()
foo.show()</code></pre>
<p><img src="https://www.mycute.cn/static/umeditor/php/upload/20190828/15669736689501.png" alt="img"></p>
<ul>
<li>我们可以认为原型prototype是类Foo的一个属性，而所有用Foo类实例化的对象，都将拥有这个属性中的所有内容，包括变量和方法。比如上图中的foo对象，其天生就具有foo.show()方法。在js中，所有的对象都是从各种基础对象继承下来的，所以每个对象都有他的父类，通过prototype可以直接操作修改父类的对象。</li>
</ul>
<p><img src="https://www.mycute.cn/static/umeditor/php/upload/20190828/15669747911191.png" alt="img"></p>
<ul>
<li>一般函数默认的<code>prototype</code>是一个类型为<code>&quot;object&quot;</code>的对象，它有两个属性：<code>constructor</code>和 <code>__proto__</code>。其中<code>constructor</code>属性指向这个函数自身，<code>__proto__</code>属性指向<code>Object.prototype</code>，这说明<strong>一般</strong>函数的<code>prototype</code>属性是由<code>Object</code>函数生成的.</li>
</ul>
<h1 id="JavaScript原型链继承"><a href="#JavaScript原型链继承" class="headerlink" title="JavaScript原型链继承"></a>JavaScript原型链继承</h1><p><img src="https://www.mycute.cn/static/umeditor/php/upload/20190828/1566975471640.png" alt="img"></p>
<pre><code class="javascript">function Father() {
    this.first_name = &#39;Donald&#39;
    this.last_name = &#39;Trump&#39;
}

function Son() {
    this.first_name = &#39;Melania&#39;
}

Son.prototype = new Father()

let son = new Son()
console.log(`Name: ${son.first_name} ${son.last_name}`)</code></pre>
<p>最终出来的结果很明显，son中并没有last_name这个属性那么他会到原型链上查找，那么最终打印出来的<code>son.last_name</code>那会是<code>Trump</code></p>
<p><img src="https://www.mycute.cn/static/umeditor/php/upload/20190828/15669757963394.png" alt="img"></p>
<h1 id="原型链污染攻击"><a href="#原型链污染攻击" class="headerlink" title="原型链污染攻击"></a>原型链污染攻击</h1><pre><code class="javascript">// foo是一个简单的JavaScript对象
let foo = {bar: 1}

// foo.bar 此时为1
console.log(foo.bar)

// 修改foo的原型（即Object）
foo.__proto__.bar = 2

// 由于查找顺序的原因，foo.bar仍然是1
console.log(foo.bar)

// 此时再用Object创建一个空的zoo对象
let zoo = {}

// 查看zoo.bar
console.log(zoo.bar)
//最后，虽然zoo是一个空对象{}，但zoo.bar的结果居然是2：</code></pre>
<p><img src="https://www.mycute.cn/static/umeditor/php/upload/20190828/15669760404403.png" alt="img"></p>
<p>原因也显而易见：因为前面我们修改了foo的原型foo.<strong>proto</strong>.bar = 2，而foo是一个Object类的实例，所以实际上是修改了Object这个类，给这个类增加了一个属性bar，值为2。</p>
<p>后来，我们又用Object类创建了一个zoo对象let zoo = {}，zoo对象自然也有一个bar属性了。</p>
<p>那么，在一个应用中，如果攻击者控制并修改了一个对象的原型，那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染。</p>
<h1 id="哪些情况下原型链会被污染？"><a href="#哪些情况下原型链会被污染？" class="headerlink" title="哪些情况下原型链会被污染？"></a>哪些情况下原型链会被污染？</h1><p>在实际应用中，哪些情况下可能存在原型链能被攻击者修改的情况呢？</p>
<p>我们思考一下，哪些情况下我们可以设置<strong>proto</strong>的值呢？其实找找能够控制数组（对象）的“键名”的操作即可：</p>
<p>对象merge<br> 对象clone（其实内核就是将待操作的对象merge到一个空对象中）<br> 以对象merge为例，我们想象一个简单的merge函数：</p>
<pre><code>function merge(target, source) {
    for (let key in source) {
        if (key in source &amp;&amp; key in target) {
            merge(target[key], source[key])
        } else {
            target[key] = source[key]
        }
    }
}
123456789</code></pre><p>在合并的过程中，存在赋值的操作target[key] = source[key]，那么，这个key如果是<strong>proto</strong>，是不是就可以原型链污染呢？</p>
<p>我们用如下代码实验一下：</p>
<pre><code>let o1 = {}
let o2 = {a: 1, &quot;__proto__&quot;: {b: 2}}
merge(o1, o2)
console.log(o1.a, o1.b)

o3 = {}
console.log(o3.b)
1234567</code></pre><p>结果是，合并虽然成功了，但原型链没有被污染：</p>
<p><img src="https://www.mycute.cn/static/umeditor/php/upload/20190828/15669765556435.png" alt="img"></p>
<p>这是因为，我们用JavaScript创建o2的过程（let o2 = {a: 1, “<strong>proto</strong>”: {b: 2}}）中，<strong>proto</strong>已经代表o2的原型了，此时遍历o2的所有键名，你拿到的是[a, b]，<strong>proto</strong>并不是一个key，自然也不会修改Object的原型。</p>
<p>那么，如何让<strong>proto</strong>被认为是一个键名呢？</p>
<p>我们将代码改成如下：</p>
<pre><code>let o1 = {}
let o2 = JSON.parse(&#39;{&quot;a&quot;: 1, &quot;__proto__&quot;: {&quot;b&quot;: 2}}&#39;)
merge(o1, o2)
console.log(o1.a, o1.b)

o3 = {}
console.log(o3.b)
1234567</code></pre><p>可见，新建的o3对象，也存在b属性，说明Object已经被污染：</p>
<p><img src="https://www.mycute.cn/static/umeditor/php/upload/20190828/15669765952903.png" alt="img"></p>
<p>这是因为，JSON解析的情况下，<strong>proto</strong>会被认为是一个真正的“键名”，而不代表“原型”，所以在遍历o2的时候会存在这个键。</p>
<p>merge操作是最常见可能控制键名的操作，也最能被原型链攻击，很多常见的库都存在这个问题。</p>
<h1 id="文章来源"><a href="#文章来源" class="headerlink" title="文章来源"></a>文章来源</h1><p><a href="https://xz.aliyun.com/t/2802" target="_blank" rel="noopener">https://xz.aliyun.com/t/2802</a></p>
<p><a href="https://blog.csdn.net/qq_41107295/article/details/95789944" target="_blank" rel="noopener">https://blog.csdn.net/qq_41107295/article/details/95789944</a></p>
<p><a href="https://www.leavesongs.com/PENETRATION/javascript-prototype-pollution-attack.html#0x01-prototype__proto" target="_blank" rel="noopener">https://www.leavesongs.com/PENETRATION/javascript-prototype-pollution-attack.html#0x01-prototype__proto</a>__</p>

	</div>
	<div class="meta split">
		
			<span>本文总阅读量 <span id="busuanzi_value_page_pv"></span> 次</span>
		
		<time class="post-date" datetime="2019-08-27T14:55:57.000Z" itemprop="datePublished">2019-08-27</time>
	</div>
</article>

<!--评论-->

	
<div class="ds-thread" data-thread-key="JavaScript原型链污染攻击学习笔记" data-title="(转载)JavaScript原型链污染攻击学习笔记" data-url="http://www.plasf.cn/2019/08/27/JavaScript原型链污染攻击学习笔记/"></div>
<script type="text/javascript">

var duoshuoQuery = {short_name:"yumemor"};
	(function() {
		var ds = document.createElement('script');
		ds.type = 'text/javascript';ds.async = true;
		ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
		ds.charset = 'UTF-8';
		(document.getElementsByTagName('head')[0]
		 || document.getElementsByTagName('body')[0]).appendChild(ds);
	})();
</script>


  
</div>


  <svg id="bigTriangleColor" width="100%" height="40" viewBox="0 0 100 102" preserveAspectRatio="none">
    <path d="M0 0 L50 100 L100 0 Z"></path>
  </svg>

  


  <div class="wrapper"></div>





<div class="fat-footer">
	<div class="wrapper">
		<div class="layout layout--center">
			<div class="layout__item palm-mb">
				<div class="media">
					<img class="headimg" src='/assets/blogImg/litten.png' alt='XiaoLeung'>
					<div class="media__body">
						<h4>兵至如归-Xiaoleung&#39;s Blog</h4>
						<p class='site-description'>Don&#39;t forget why we started</p>
					</div>
				</div>
				<div class="author-contact">
					<ul>
						
							
							<li>
				        		<a href="https://github.com/sharpleung" target="_blank">
				        			
				        				<i class="iconfont icon-github"></i>
				        			
				        		</a>
				        	</li>
						
					</ul>
				</div>
			</div>
		</div>
	</div>
</div>

<footer class="footer" role="contentinfo">
	<div class="wrapper wrapper--wide split split--responsive">
<a href="http://beian.miit.gov.cn/">粤ICP备18132442号-1</a><br>
<a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=44011202000643" style="display:inline-block;text-decoration:none;height:20px;line-height:20px;"><img src="http://beian.gov.cn/img/ghs.png" style="float:left;"/><p style="float:left;height:20px;line-height:20px;margin: 0px 0px 0px 5px; color:#939393;">粤公网安备 44011202000643号</p></a><br>

		
			<span>本站总访问量 <span id="busuanzi_value_site_pv"></span> 次, 访客数 <span id="busuanzi_value_site_uv"></span> 人次</span>
		
		<span>Theme by <a href="http://github.com/justpsvm">justpsvm</a>. Powered by <a href="http://hexo.io">Hexo</a></span>
	</div>
</footer>

	<!-－这里导入了 lib.js 里面涵盖了 jQuery 等框架 所以注释掉-->
	<!--<script src="http://lib.sinaapp.com/js/jquery/2.0/jquery.min.js"></script>-->
	<script src="/js/lib.js"></script>
	<script src="/js/google-code-prettify/prettify.js"></script>
	<script src="/js/module.js"></script>
	<script src="/js/script.js"></script>
	
		<script async src="http://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>
	
	<script type='text/javascript'>
		//代码高亮
		$(document).ready(function(){
	 		$('pre').addClass('prettyprint linenums').attr('style', 'overflow:auto;');
   			prettyPrint();
		});
	</script>
	<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script><script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>

<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
 <script type="text/javascript"> /* 鼠标点击特效 - 7Core.CN */ var a_idx = 0;jQuery(document).ready(function($) {$("body").click(function(e) {var a = new Array("富强", "民主", "文明", "和谐", "自由", "平等", "公正" ,"法治", "爱国", "敬业", "诚信", "友善");var $i = $("<span/>").text(a[a_idx]); a_idx = (a_idx + 1) % a.length;var x = e.pageX,y = e.pageY;$i.css({"z-index": 100000000,"top": y - 20,"left": x,"position": "absolute","font-weight": "bold","color": "#ff6651"});$("body").append($i);$i.animate({"top": y - 180,"opacity": 0},1500,function() {$i.remove();});});}); </script>

